package cn.demoncat.util.mybatis.base;

import cn.demoncat.util.exception.BizRuntimeException;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 描述：树型数据常用Service操作
 *
 * @author 延晓磊
 *
 * @since 2017年3月26日
 */
public interface BaseTreeService<T extends BaseTreeEntity<T,P>, P extends Serializable> extends BaseService<T, P>{

	/**
	 * 获取名称
	 * 
	 * @param id	ID
	 * 
	 * @return [父,子]
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年1月17日
	 */
	List<String> findName(P id);
	
	/**
	 * 获取名称集
	 * 
	 * @param ids	ID集
	 * 
	 * @return {id : [父,子]}
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年1月17日
	 */
	Map<P, List<String>> findNames(Collection<P> ids);
	
	/**
	 * 获取子节点数
	 * 
	 * @param id
	 */
	long getSubCount(P id);
	
	/**
	 * 获取子节点
	 * 
	 * @param id
	 */
	List<T> getChildren(P id);
	
	/**
	 * 获取子节点
	 * 
	 * @param id
	 * @param sort	排序方式
	 */
	List<T> getChildren(P id, String sort);
	
	/**
	 * 变更节点的subCount
	 * 
	 * @param id
	 * @param add	true递增，false递减
	 * 
	 * 注意：事务须设置为READ_COMMITTED，否则更新节点使用乐观锁时无法重试
	 */
	void updSubCount(P id, boolean add);
	
	/**
	 * 树型插入
	 * 
	 * 1、插入时校验 o.parentId和name非空
	 * 2、判断sort为空时，设置默认sort
	 * 
	 * @param o	对象
	 * 
	 * @return 成功返回1，失败返回0，参数有问题抛异常
	 */
	int saveTree(T o);
	
	/**
	 * 树型插入，CAS修改父节点的subCount
	 * 
	 * 1、插入时校验 o.parentId和name非空
	 * 2、判断sort为空时，设置默认sort
	 * 3、插入成功时，CAS方式修改父节点的subCount
	 * 
	 * 注意：事务须设置为READ_COMMITTED，否则更新父节点使用乐观锁时无法重试
	 * 
	 * @param o	对象
	 * 
	 * @return 成功返回1，失败返回0，参数有问题抛异常
	 */
	int saveTreeCas(T o);
	
	/**
	 * 树型更新
	 * 
	 * 1、排除null属性的字段
	 * 2、如果o或id为null，抛异常
	 * 3、禁止name为空
	 * 4、禁止修改sort,parentId,nodeLevel,subCount字段
	 * 
	 * @param o
	 * @return 修改记录数
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月1日
	 */
	int updateTree(T o);
	
	/**
	 * 树型条件更新
	 * 
	 * 1、排除null属性的字段
	 * 2、如果o或id为null，抛异常
	 * 3、如果o.id为null，将更新condition匹配的所有数据；如果o.id非null，将判断id对应的数据是否满足condition
	 * 4、禁止name为空
	 * 5、禁止修改sort,parentId,nodeLevel,subCount字段
	 * 
	 * @param o
	 * @param condition	条件
	 * @return 修改记录数
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年8月1日
	 */
	int updateTree(T o, Map<String, Object> condition);

	/**
	 * 根据ID删除
	 *
	 * @param id
	 * @return 删除的数据，数据不存在/删除失败返回null，级联抛异常
	 */
	T deleteAndGetTree(P id);

	/**
	 * 根据ID删除
	 *
	 * @param id
	 * @param msg	级联的异常消息
	 * @return 删除的数据，数据不存在/删除失败返回null，级联抛异常
	 */
	T deleteAndGetTree(P id, String msg);

	/**
	 * 树型删除
	 * 
	 * 1、查询数据是否存在：不存在返回0
	 * 2、校验子节点：有子节点返回-1
	 * 3、删除：数据存在返回1，数据不存在返回0
	 * 
	 * @param id
	 * 
	 * @return 成功返回1，不存在返回0，有子节点返回-1
	 */
	int deleteTree(P id);
	
	/**
	 * 树型删除，CAS修改父节点的subCount
	 * 
	 * 1、查询数据是否存在：不存在返回0
	 * 2、校验子节点：有子节点返回-1
	 * 3、删除：数据存在返回1，数据不存在返回0
	 * 4、CAS修改父节点的subCount：返回1
	 * 
	 * 注意：事务须设置为READ_COMMITTED，否则更新父节点使用乐观锁时无法重试
	 * 
	 * @param id
	 * 
	 * @return 成功返回1，不存在返回0，有子节点返回-1
	 */
	int deleteTreeCas(P id);
	
	/**
	 * 树型删除，校验结果
	 * 
	 * 1、校验数据不存在：0/抛异常
	 * 2、校验有子节点：-1/抛异常
	 * 
	 * @param id
	 * @param condition
	 * @param canNull		允许数据不存在：true返回0，false抛异常
	 * @param canHasChild	允许有子节点：true返回-1，false抛异常
	 * @param childErrMsg	有子节点时的错误信息，为空时默认消息“请先删除子节点”
	 * 
	 * @return 成功返回1，有子节点时返回-1或异常，数据不存在返回0或异常
	 */
	int deleteTreeVali(P id, Map<String, Object> condition, boolean canNull, boolean canHasChild, String childErrMsg);
	
	/**
	 * 树型删除，校验结果，CAS修改父节点的subCount
	 * 
	 * 1、校验数据不存在：0/抛异常
	 * 2、校验有子节点：-1/抛异常
	 * 3、CAS修改父节点的subCount：返回1
	 * 
	 * 注意：事务须设置为READ_COMMITTED，否则更新父节点使用乐观锁时无法重试
	 * 
	 * @param id
	 * @param condition
	 * @param canNull		允许数据不存在：true返回0，false抛异常
	 * @param canHasChild	允许有子节点：true返回-1，false抛异常
	 * @param childErrMsg	有子节点时的错误信息，为空时默认消息“请先删除子节点”
	 * 
	 * @return 成功返回1，有子节点时返回-1或异常，数据不存在返回0或异常
	 */
	int deleteTreeValiCas(P id, Map<String, Object> condition, boolean canNull, boolean canHasChild, String childErrMsg);
	
	/**
	 * 树型删除，校验结果
	 * 
	 * @param id
	 * @param condition
	 * @param childErrMsg	有子节点时的错误信息，为空时默认消息“请先删除子节点”
	 * 
	 * @return 成功返回1
	 * 
	 * @throws BizRuntimeException 数据不存在，有子节点
	 */
	int deleteTreeVali(P id, Map<String, Object> condition, String childErrMsg);
	
	/**
	 * 树型删除，校验结果，CAS修改父节点的subCount
	 * 
	 * 注意：事务须设置为READ_COMMITTED，否则更新父节点使用乐观锁时无法重试
	 * 
	 * @param id
	 * @param condition
	 * @param childErrMsg	有子节点时的错误信息，为空时默认消息“请先删除子节点”
	 * 
	 * @return 成功返回1
	 * 
	 * @throws BizRuntimeException 数据不存在，有子节点
	 */
	int deleteTreeValiCas(P id, Map<String, Object> condition, String childErrMsg);
 
	/**
	 * 树型删除，校验结果
	 * 
	 * @param id
	 * @param childErrMsg	有子节点时的错误信息，为空时默认消息“请先删除子节点”
	 * 
	 * @return 成功返回1
	 * 
	 * @throws BizRuntimeException 数据不存在，有子节点
	 */
	int deleteTreeVali(P id, String childErrMsg);
	
	/**
	 * 树型删除，校验结果，CAS修改父节点的subCount
	 * 
	 * 注意：事务须设置为READ_COMMITTED，否则更新父节点使用乐观锁时无法重试
	 * 
	 * @param id
	 * @param childErrMsg	有子节点时的错误信息，为空时默认消息“请先删除子节点”
	 * 
	 * @return 成功返回1
	 * 
	 * @throws BizRuntimeException 数据不存在，有子节点
	 */
	int deleteTreeValiCas(P id, String childErrMsg);
	
	/**
	 * 树型删除，校验结果
	 * 
	 * @param id
	 * 
	 * @return 成功返回1
	 * 
	 * @throws BizRuntimeException 数据不存在，有子节点
	 */
	int deleteTreeVali(P id);
	
	/**
	 * 树型删除，校验结果，CAS修改父节点的subCount
	 * 
	 * 注意：事务须设置为READ_COMMITTED，否则更新父节点使用乐观锁时无法重试
	 * 
	 * @param id
	 * 
	 * @return 成功返回1
	 * 
	 * @throws BizRuntimeException 数据不存在，有子节点
	 */
	int deleteTreeValiCas(P id);

	

	
}
